#version 460
#extension GL_GOOGLE_include_directive : enable
#extension GL_EXT_scalar_block_layout : enable
#extension GL_EXT_buffer_reference2 : require
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require

#include "../../../../core/shader_binding_ID.h"
#include "../../../../core/shader_std.h" 
#include "../../../../core/shader_built_in_functions.h"
#include "../../../../core/shader_ray.h"

#include "../../../../core/shader_mesh.h" 
//#include "../../../../core/shader_taster_geomFaceAttr.h"

layout(triangles) in;
layout(triangle_strip, max_vertices=3) out;


layout(location = 0) in vec4 vColor[];
layout(location = 1) in vec3 vNormal[];
layout(location = 2) in vec3 vCamera[][4];
layout(location = 8) in uint vVertIndexID[];
layout(location = 9) in uint vMeshOffset[];
layout(location = 20) in uint vFaceOffset[];

layout(location = DEF_BINDING_LocationBindID_Vert) in vec3 vVert[];
layout(location = DEF_BINDING_LocationBindID_FaceAttr) in S_Geom_MeshDrawProp vFaceAttr[];
layout(location = DEF_BINDING_LocationBindID_RotMat) in mat4 vTranformMat[];

//layout(location = DEF_BINDING_TasterBindID_MeshAtt) in uint vMeshAtt_Offset[];
//layout(location = DEF_BINDING_TasterBindID_MaterialAtt) in uint vMaterialAtt_Offset[];

layout(binding = DEF_BINDING_ObMesh, scalar) readonly buffer B_ObMesh { S_ObMesh m_ObMesh[]; };
layout(binding = DEF_BINDING_TasterBindID_Face, scalar) readonly buffer B_Faces { S_FaceElement m_Face[]; };
layout(binding = DEF_BINDING_TasterBindID_TexCoord, scalar) readonly buffer B_TexCoord { vec2 m_TexCoord[]; };
layout(binding = DEF_BINDING_TasterBindID_TexIndex, scalar) readonly buffer B_TexIndex { uvec3 m_TexIndex[]; };

layout(binding = DEF_BINDING_Render_GlobalParam, scalar) readonly buffer B_GlobalParam { S_GlobalParam gGlobalParam; };
layout(binding = DEF_BINDING_Material_AttrIndex, scalar) readonly buffer Material_CustomAttr { S_CustomAttr CustomAttrPtr[]; } MaterialCA_GParam;
layout(binding = DEF_BINDING_Face_AttrIndex, scalar) readonly buffer Face_CustomAttr { S_CustomAttr CustomAttrPtr[]; } customAttr_GParam;

in gl_PerVertex {
	vec4 gl_Position;
	float gl_PointSize;
}gl_in[];


layout(location = 0) out vec4 outColor;
layout(location = 1) out vec3 outNormal;
layout(location = 2) out vec3 outCamera[4];
layout(location = 8) flat out uint outPrimitiveID;
layout(location = 9) flat out uint outMeshOffset;
layout(location = 10) out vec3 outBarycentrics;
layout(location = 11) out vec2 outUV[4];
//layout(location = 6) out float outDepthScale;

out gl_PerVertex {
	vec4	gl_Position;
};

layout(location = DEF_BINDING_LocationBindID_Vert) out vec3 gVert;
layout(location = DEF_BINDING_TasterBindID_MaterialID) out flat S_FaceAttr Element;




void main(void){
	S_ObMesh      Resource_ObMesh = m_ObMesh[vMeshOffset[0]];
	//B_Faces       mesh_face       = B_Faces(Resource_ObMesh.m_AddressFaces);
	//S_FaceElement Element         = mesh_face.Element[gl_PrimitiveIDIn];
	uint primitiveID = gl_PrimitiveIDIn + vFaceOffset[0];
	//uint primitiveID = gl_PrimitiveIDIn;
	S_FaceElement face = m_Face[vFaceAttr[0].Offset_Face + primitiveID];

	vec3 edgeA = normalize(vVert[1] - vVert[0]);
	vec3 edgeB = normalize(vVert[2] - vVert[0]);
	
	vec3 Normal = cross(edgeA, edgeB);
	
	uvec3 uvIndex[4];
	
	if(Resource_ObMesh.uvLayerAndOffset.x > 0) {
		uvIndex[0] = m_TexIndex[ primitiveID + Resource_ObMesh.uvIndexOffset012.x + Resource_ObMesh.uvLayerAndOffset.z];
		uvIndex[1] = m_TexIndex[ primitiveID + Resource_ObMesh.uvIndexOffset012.y + Resource_ObMesh.uvLayerAndOffset.z];
		uvIndex[2] = m_TexIndex[ primitiveID + Resource_ObMesh.uvIndexOffset012.z + Resource_ObMesh.uvLayerAndOffset.z];
		uvIndex[3] = m_TexIndex[ primitiveID + Resource_ObMesh.uvIndexOffset345.x + Resource_ObMesh.uvLayerAndOffset.z];
	}else{
		for(int i=0; i<4; ++i){
			uvIndex[i] = uvec3(0);
		}
	}


	//float depth = vDepthScale[0];
	//depth = 0.01;
	for(int i=0; i<3; ++i){
		//uint id = i;
		outNormal = Normal;
		outPrimitiveID = primitiveID;
		outMeshOffset = vMeshOffset[0];
		
		Element.MaterialID = face.MaterialID;
		Element.MaterialSlot = face.MaterialSlot;
		Element.Offset_MeshAttr = vFaceAttr[0].Offset_MeshAttr;
		Element.Offset_MaterialAttr = vFaceAttr[0].Offset_MaterialAttr;
		//gMaterialID = 0;
		
		//outDepthScale = depth;
		switch(i){
			case 0: 
				outBarycentrics = vec3(1,0,0); 
				for(int uvid=0; uvid<4; ++uvid){
					outUV[uvid] = m_TexCoord[uvIndex[uvid].x + Resource_ObMesh.uvLayerAndOffset.y];
				}
				break;
			case 1: 
				outBarycentrics = vec3(0,1,0); 
				for(int uvid=0; uvid<4; ++uvid){
					outUV[uvid] = m_TexCoord[uvIndex[uvid].y + Resource_ObMesh.uvLayerAndOffset.y];
				}
				break;
			case 2: 
				outBarycentrics = vec3(0,0,1); 
				for(int uvid=0; uvid<4; ++uvid){
					outUV[uvid] = m_TexCoord[uvIndex[uvid].z + Resource_ObMesh.uvLayerAndOffset.y];
				}
				break;
		}


		gVert = vVert[i];
		outColor = vColor[i];
		outColor.a = 1;
		gl_Position = gl_in[i].gl_Position;
		outCamera[0] = vCamera[i][0];
		outCamera[1] = vCamera[i][1];
		outCamera[2] = vCamera[i][2];
		outCamera[3] = vCamera[i][3];
		
		EmitVertex();
	}

	EndPrimitive();
}



